package proyectoX;

import java.util.ArrayList;
import java.util.Random;
import java.util.Stack;





/**
 * Clase abstracta que implementa robot
 * @author Daprotis Mauro - Heiland Federico
 *
 */

public abstract class Robot {
	protected Grilla g;
	protected Game game;
	protected int Puntaje,Combustible,Direccion,fila,col,municion,sizeBaul;
	protected boolean pincel,Cpincel; //Cpincel true=blanco false=negro;
	protected ArrayList<Entity> balas;
	protected Stack<Objeto> baul;
	
	/**
	 * Metodo que carga el Coleccionable que se encuntre en la celda ubicada detras del robot.
	 */
	public void cargar(){
		if (sizeBaul<15){
			Celda c=null;
			int pFila=-1;
			int pCol=-1;
			switch (Direccion){
				case 0: 
					{
					pFila=fila+1;pCol=col;
					};break;
				case 1: 
					{
					pFila=fila;pCol=col-1;
					};break;
				case 2:
					{
					pFila=fila-1;pCol=col;
					};break;
				case 3: 
					{
					pFila=fila;pCol=col+1;
					};break;
			}
			c=g.getCelda(pFila, pCol);
			if (c!=null){
				if (c.getObjeto()!=null){
					switch (c.getObjeto().getTipo()){
					case 0:
					case 1: {
						sizeBaul++;
						baul.push(c.getObjeto());
						g.setCelda(pFila, pCol, c.getTipo(), -1);
					};break;
					default: break;
						
					}
				}
			}
		}
	}
	
	/**
	 * Metodo que descarga un coleccionable del baul en la celda detras del robot.
	 */
	public void descargar(){
		if (sizeBaul!=0){
			Celda c=null;
			int pFila=-1;
			int pCol=-1;
			switch (Direccion){
				case 0: 
					{
					pFila=fila+1;pCol=col;
					};break;
				case 1: 
					{
					pFila=fila;pCol=col-1;
					};break;
				case 2:
					{
					pFila=fila-1;pCol=col;
					};break;
				case 3: 
					{
					pFila=fila;pCol=col+1;
					};break;
			}
			c=g.getCelda(pFila, pCol);
			if (c!=null){
				if (c.getObjeto()==null){
				g.setCelda(pFila, pCol, c.getTipo(), baul.pop().getTipo());
				sizeBaul--;
				}
	}
		
	}
	}
	/**
	 * Metodo de disparo para la clase de robot Militar.
	 */
	public abstract void disparar();
	/**
	 * Metodo que despliega/repliega el pincel del robot.
	 */
	public void desplegarPincel(){
		if (pincel) pincel=false;
		else pincel=true;
	}
	/**
	 * Metodo que cambia el color del pincel.
	 */
	public void cambiarColor(){
		if (Cpincel) Cpincel=false;
		else Cpincel=true;
	}
	//Retorna 0 si el pincel no esta desplegado, 1 si esta desplegado en Blanco y 2 en negro.
	/**
	 * Metodo para consultar el estado del pincel.
	 * @return 0 sin pincel, 1 pincel blanco, 2 pincel negro.
	 */
	public int getPincel(){
		if (pincel) 
			if (Cpincel) return 1;
			else return 2;
		else return 0;
		
	}
	/**
	 * Metodo para consultar las balas restantes.
	 * @return balas restantes
	 */
	public int getMunicion(){
		return municion;
	}
	/**
	 * Metodo para consultar las balas disparadas 
	 * @return
	 */
	public ArrayList<Entity> getBalas(){
		return balas;
		
	}
	/**
	 * Metodo para consultar el puntaje actual.
	 * @return puntaje actual.
	 */
	public int getPuntaje(){
		return Puntaje;
	}
	/**
	 * Metodo para consultar el combustible restante.
	 * @return combustible restante.
	 */
	public int getCombustible(){
		return Combustible;
	}
	/**
	 * Consulta la fila del robot.
	 * @return fila
	 */
	public int getFila(){
		return fila;
	}
	/**
	 * Consulta columna del robot.
	 * @return columna.
	 */
	public int getCol(){
		return col;
	}
	/**
	 * Consulta la direccion en la que apunta el robot.
	 * Direcicon:
	 * 0 norte
	 * 1 este
	 * 2 sur
	 * 3 oeste
	 * @return direccion
	 */
	public int getDireccion(){
		return Direccion;
	}
	/**
	 * Rota el robot.
	 * 0 rota izq
	 * 1 rota derecha
	 * @param e sentido en el cual rota.
	 */
	public void rotar(int e){
		Combustible--;
		if (e==1) {
			Direccion=(Direccion+1)%4;
		}
		else {
			if (Direccion==0) Direccion=3;
			else Direccion=Direccion-1;
		}
	}
	/**
	 * Metodo para permitir avanzar por la grilla al robot.
	 * @return coordenadas antiguas.
	 */
	public abstract int[] avanzar();
	/**
	 * Metodo para remover una bala que haya impactado.
	 * @param b bala a remover.
	 */
	public void removeBala(Entity b){
		balas.remove(b);
	}
	/**
	 * Metodo que maneja el impacto de una bala con un obstaculo.
	 * @param b bala
	 * @param o obstaculo
	 */
	public void colision(Entity b,Obstaculo o){
		balas.remove(b);
		
		o.impacto();
		if (o.getResistencia()==0) 
			{
			if (o.tienePremio())
			{
				int tp=premioRandom();
				g.setCelda(o.getX()/40, o.getY()/40,(g.getCelda(o.getX()/40, o.getY()/40)).getTipo(), tp);
			}
			else
				g.setCelda(o.getX()/40, o.getY()/40,(g.getCelda(o.getX()/40, o.getY()/40)).getTipo(), -1);			
			g.getListaOb().remove(o);
			}
		
	}
	
	private int premioRandom(){
		Random r = new Random();
		int valor = r.nextInt(4)+1;
		return valor;
	}
	/**
	 * Consulta cantidad de objetos en el baul.
	 * @return objetos en el baul.
	 */
	public int getSizeBaul(){
		return baul.size();
	}
}

